//! JIT预编译配置
//!
//! 提供构建阶段的JIT预编译配置选项

use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::path::Path;

/// JIT预编译配置
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PrecompileConfig {
    /// 是否启用预编译
    pub enabled: bool,
    
    /// 优化级别
    pub optimization_level: OptimizationLevel,
    
    /// 预编译模块列表
    pub modules: HashMap<String, ModuleConfig>,
    
    /// 输出目录
    pub output_dir: String,
    
    /// 缓存策略
    pub cache_strategy: CacheStrategy,
}

/// 优化级别
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
pub enum OptimizationLevel {
    /// 无优化（快速编译）
    None,
    /// 基本优化
    Basic,
    /// 高级优化
    Advanced,
    /// 最大优化
    Maximum,
}

/// 模块配置
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ModuleConfig {
    /// 输入文件路径
    pub input_path: String,
    
    /// 输出文件名
    pub output_name: String,
    
    /// 模块特定优化
    pub specific_optimization: Option<OptimizationLevel>,
    
    /// 是否强制重新编译
    pub force_recompile: bool,
}

/// 缓存策略
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum CacheStrategy {
    /// 总是重新编译
    AlwaysRecompile,
    /// 根据文件修改时间
    TimestampBased,
    /// 根据文件内容哈希
    ContentHashBased,
    /// 永不重新编译
    NeverRecompile,
}

impl PrecompileConfig {
    /// 创建默认配置
    pub fn new() -> Self {
        Self {
            enabled: true,
            optimization_level: OptimizationLevel::Advanced,
            modules: HashMap::new(),
            output_dir: "target/precompiled".to_string(),
            cache_strategy: CacheStrategy::ContentHashBased,
        }
    }
    
    /// 添加模块配置
    pub fn add_module(&mut self, name: &str, config: ModuleConfig) {
        self.modules.insert(name.to_string(), config);
    }
    
    /// 获取模块配置
    pub fn get_module(&self, name: &str) -> Option<&ModuleConfig> {
        self.modules.get(name)
    }
    
    /// 加载配置文件
    pub fn from_file(path: &str) -> Result<Self, String> {
        let content = std::fs::read_to_string(path)
            .map_err(|e| format!("无法读取配置文件: {}", e))?;
        
        serde_json::from_str(&content)
            .map_err(|e| format!("配置文件格式错误: {}", e))
    }
    
    /// 保存配置文件
    pub fn save_to_file(&self, path: &str) -> Result<(), String> {
        let content = serde_json::to_string_pretty(self)
            .map_err(|e| format!("序列化配置失败: {}", e))?;
        
        std::fs::write(path, content)
            .map_err(|e| format!("写入配置文件失败: {}", e))
    }
    
    /// 获取模块的优化级别
    pub fn get_module_optimization(&self, module_name: &str) -> OptimizationLevel {
        self.modules
            .get(module_name)
            .and_then(|config| config.specific_optimization)
            .unwrap_or(self.optimization_level)
    }
    
    /// 检查是否需要重新编译
    pub fn should_recompile(&self, module_name: &str, input_path: &str) -> bool {
        if !self.enabled {
            return false;
        }
        
        let module_config = match self.modules.get(module_name) {
            Some(config) => config,
            None => return true,
        };
        
        if module_config.force_recompile {
            return true;
        }
        
        let output_path = Path::new(&self.output_dir)
            .join(format!("{}.pre", module_config.output_name));
        
        match self.cache_strategy {
            CacheStrategy::AlwaysRecompile => true,
            CacheStrategy::NeverRecompile => false,
            CacheStrategy::TimestampBased => {
                let input_modified = match std::fs::metadata(input_path) {
                    Ok(meta) => meta.modified().unwrap(),
                    Err(_) => return true,
                };
                
                let output_modified = match std::fs::metadata(&output_path) {
                    Ok(meta) => meta.modified().unwrap(),
                    Err(_) => return true,
                };
                
                input_modified > output_modified
            }
            CacheStrategy::ContentHashBased => {
                use std::collections::hash_map::DefaultHasher;
                use std::hash::{Hash, Hasher};
                
                let input_hash = {
                    let mut hasher = DefaultHasher::new();
                    let content = match std::fs::read_to_string(input_path) {
                        Ok(content) => content,
                        Err(_) => return true,
                    };
                    content.hash(&mut hasher);
                    hasher.finish()
                };
                
                let output_hash = {
                    let mut hasher = DefaultHasher::new();
                    let content = match std::fs::read(&output_path) {
                        Ok(content) => content,
                        Err(_) => return true,
                    };
                    content.hash(&mut hasher);
                    hasher.finish()
                };
                
                input_hash != output_hash
            }
        }
    }
}

impl Default for PrecompileConfig {
    fn default() -> Self {
        Self::new()
    }
}



/// 预编译配置示例
pub fn create_example_config() -> PrecompileConfig {
    let mut config = PrecompileConfig::new();
    
    config.add_module("math", ModuleConfig {
        input_path: "src/stdlib/math.pip".to_string(),
        output_name: "math".to_string(),
        specific_optimization: Some(OptimizationLevel::Maximum),
        force_recompile: false,
    });
    
    config.add_module("io", ModuleConfig {
        input_path: "src/stdlib/io.pip".to_string(),
        output_name: "io".to_string(),
        specific_optimization: Some(OptimizationLevel::Basic),
        force_recompile: false,
    });
    
    config.add_module("string", ModuleConfig {
        input_path: "src/stdlib/string.pip".to_string(),
        output_name: "string".to_string(),
        specific_optimization: None, // 使用默认优化级别
        force_recompile: false,
    });
    
    config
}

/// 构建时预编译函数
pub fn precompile_with_config(config: &PrecompileConfig) -> Result<(), String> {
    if !config.enabled {
        return Ok(());
    }
    
    // 创建输出目录
    std::fs::create_dir_all(&config.output_dir)
        .map_err(|e| format!("创建输出目录失败: {}", e))?;
    
    // 预编译所有模块
    for (name, module_config) in &config.modules {
        let input_path = &module_config.input_path;
        let output_name = &module_config.output_name;
        
        if !config.should_recompile(name, input_path) {
            println!("跳过模块 '{}' 的预编译（缓存命中）", name);
            continue;
        }
        
        let optimization_level = config.get_module_optimization(name);
        let output_path = Path::new(&config.output_dir)
            .join(format!("{}.pre", output_name));
        
        println!("预编译模块: {} -> {}", name, output_path.display());
        
        // 这里应该调用实际的预编译器
        // 为简化实现，使用模拟预编译
        let content = std::fs::read_to_string(input_path)
            .map_err(|e| format!("读取文件失败: {}", e))?;
        
        let bytecode = compile_source_to_bytecode(&content);
        
        std::fs::write(&output_path, bytecode)
            .map_err(|e| format!("写入文件失败: {}", e))?;
    }
    
    Ok(())
}

/// 简化的源代码编译（实际应该使用完整的编译器）
fn compile_source_to_bytecode(source: &str) -> Vec<u8> {
    let mut bytecode = Vec::new();
    
    for line in source.lines() {
        let line = line.trim();
        if line.is_empty() || line.starts_with("//") {
            continue;
        }
        
        let parts: Vec<&str> = line.split_whitespace().collect();
        if parts.is_empty() {
            continue;
        }
        
        match parts[0] {
            "push" => {
                let val = parts[1].parse::<i32>().unwrap_or(0);
                bytecode.push(0x01); // PushInt
                bytecode.extend_from_slice(&val.to_le_bytes());
            }
            "add" => bytecode.push(0x02),
            "sub" => bytecode.push(0x03),
            "mul" => bytecode.push(0x04),
            "div" => bytecode.push(0x05),
            "print" => bytecode.push(0x06),
            "halt" => bytecode.push(0x07),
            _ => {}
        }
    }
    
    bytecode
}